﻿using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;

namespace Domzs.Web.Mvc.ActionResults
{
    public class ExcelResult : ActionResult
    {
        // Fields
        private DataContext _dataContext;
        private string _fileName;
        private string[] _headers;
        private TableItemStyle _headerStyle;
        private TableItemStyle _itemStyle;
        private IQueryable _rows;
        private TableStyle _tableStyle;

        // Methods
        public ExcelResult(DataContext dataContext, IQueryable rows, string fileName)
            : this(dataContext, rows, fileName, null, null, null, null)
        {
        }

        public ExcelResult(DataContext dataContext, string fileName, IQueryable rows, string[] headers)
            : this(dataContext, rows, fileName, headers, null, null, null)
        {
        }

        public ExcelResult(DataContext dataContext, IQueryable rows, string fileName, string[] headers, TableStyle tableStyle, TableItemStyle headerStyle, TableItemStyle itemStyle)
        {
            this._dataContext = dataContext;
            this._rows = rows;
            this._fileName = fileName;
            this._headers = headers;
            this._tableStyle = tableStyle;
            this._headerStyle = headerStyle;
            this._itemStyle = itemStyle;
            if (this._tableStyle == null)
            {
                this._tableStyle = new TableStyle();
                this._tableStyle.BorderStyle = BorderStyle.Solid;
                this._tableStyle.BorderColor = Color.Black;
                this._tableStyle.BorderWidth = Unit.Parse("2px");
                this._tableStyle.CssClass = "string";
            }
            if (this._headerStyle == null)
            {
                this._headerStyle = new TableItemStyle();
                this._headerStyle.BackColor = Color.LightGray;
            }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            StringWriter writer = new StringWriter();
            HtmlTextWriter writer2 = new HtmlTextWriter(writer);
            writer2.Write("<html xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns=\"http://www.w3.org/TR/REC-html40\">");
            writer2.Write("<head><meta http-equiv=Content-Type content=\"text/html; charset=utf-8\"><meta name=ProgId content=Excel.Sheet><meta name=Generator content=\"Microsoft Excel 9\"><style type=\"text/css\">");
            writer2.Write("<!--tr {mso-height-source:auto;} td {white-space:nowrap;}.string {white-space:nowrap;font-family:Arial;mso-number-format:General;vertical-align:bottom;mso-protection:locked;} .szoveg {white-space:nowrap;font-family:Arial;mso-number-format:\"\\@\";vertical-align:bottom;mso-protection:locked;} .datum {white-space:nowrap;font-family:Arial;mso-number-format:\"Short Date\";vertical-align:bottom;mso-protection:locked;} .ido {white-space:nowrap;font-family:Arial;mso-number-format:\"\\[$-F400\\]h\\:mm\\:ss\\\\ AM\\/PM\";vertical-align:bottom;mso-protection:locked;}--></style></head>");
            writer2.Write("<body><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Label Style='border-top:solid .5pt silver;border-left:solid .5pt silver;border-right:solid .5pt silver;border-bottom:solid .5pt silver'><x:Caption>Microsoft Office Spreadsheet</x:Caption></x:Label><x:Name>Sheet1</x:Name><x:WorksheetOptions><x:Selected/><x:Height>7620</x:Height><x:Width>15240</x:Width><x:ViewableRange>1:65536</x:ViewableRange><x:Selection>A1</x:Selection><x:TopRowVisible>0</x:TopRowVisible><x:LeftColumnVisible>0</x:LeftColumnVisible><x:ProtectContents>False</x:ProtectContents><x:DefaultRowHeight>255</x:DefaultRowHeight><x:StandardWidth>2340</x:StandardWidth></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets><x:MaxHeight>80%</x:MaxHeight><x:MaxWidth>80%</x:MaxWidth></x:ExcelWorkbook></xml><![endif]-->");
            writer2.Write("<table class=string x:str>");
            if (this._headers == null)
            {
                this._headers = this._dataContext.Mapping.GetMetaType(this._rows.ElementType).PersistentDataMembers.Select<MetaDataMember, string>(delegate(MetaDataMember m)
                {
                    return m.Name;
                }).ToArray<string>();
            }
            writer2.RenderBeginTag(HtmlTextWriterTag.Thead);
            foreach (string str in this._headers)
            {
                if (this._headerStyle != null)
                {
                    this._headerStyle.AddAttributesToRender(writer2);
                }
                writer2.RenderBeginTag(HtmlTextWriterTag.Th);
                writer2.Write(str);
                writer2.RenderEndTag();
            }
            writer2.RenderEndTag();
            writer2.RenderBeginTag(HtmlTextWriterTag.Tbody);
            foreach (object obj2 in this._rows)
            {
                writer2.RenderBeginTag(HtmlTextWriterTag.Tr);
                foreach (string str2 in this._headers)
                {
                    string str3;
                    if (obj2.GetType().GetProperty(str2).GetValue(obj2, null) != null)
                    {
                        if (obj2.GetType().GetProperty(str2).PropertyType.Name == "Boolean")
                        {
                            if (obj2.GetType().GetProperty(str2).GetValue(obj2, null).ToString().ToLower() == "true")
                            {
                                str3 = "I";
                            }
                            else
                            {
                                str3 = "N";
                            }
                        }
                        else
                        {
                            str3 = ReplaceSpecialCharacters(obj2.GetType().GetProperty(str2).GetValue(obj2, null).ToString());
                        }
                    }
                    else
                    {
                        str3 = "";
                    }
                    if (this._itemStyle != null)
                    {
                        this._itemStyle.AddAttributesToRender(writer2);
                    }
                    writer2.RenderBeginTag(HtmlTextWriterTag.Td);
                    writer2.Write(HttpUtility.HtmlEncode(str3));
                    writer2.RenderEndTag();
                }
                writer2.RenderEndTag();
            }
            writer2.RenderEndTag();
            writer2.Write("</table>");
            writer2.Write("</body>");
            writer2.Write("</html>");
            WriteFile(this._fileName, "application/ms-excel", writer.ToString());
        }

        private static string ReplaceSpecialCharacters(string value)
        {
            value = value.Replace("’", "'");
            value = value.Replace("“", "\"");
            value = value.Replace("”", "\"");
            value = value.Replace("–", "-");
            value = value.Replace("…", "...");
            return value;
        }

        private static void WriteFile(string fileName, string contentType, string content)
        {
            HttpContext current = HttpContext.Current;
            current.Response.Clear();
            current.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
            current.Response.Charset = "";
            current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            current.Response.ContentType = contentType;
            current.Response.Write(content);
            current.Response.End();
        }

        // Properties
        public string FileName
        {
            get
            {
                return this._fileName;
            }
        }

        public IQueryable Rows
        {
            get
            {
                return this._rows;
            }
        }
    }
}
